#include"slide.h"


using namespace std;

//1.推线
int SlideLine::pushSingleLine(vector<Line>& polyLines, Line& slideLine, const Point offset, const bool postOn) {
	int index = -1;
	index = getPosition(polyLines, slideLine);
	if (index < 0) return -1;
	Line backupLine = slideLine;
	bool resultJudge = true;			//默认成功
	pushSingleSeg(slideLine, offset);	//推挤线段
	determineConnection(polyLines, index, slideLine);	//处理各线间位置关系
	resultJudge = judgement(backupLine, slideLine);		//判断当前推挤的线是否到达临界值  [1]true:推挤完未到达边界 [2]false:推挤完小于边界
	if (resultJudge) {
		inspectSingleLines(slideLine, polyLines);		//推挤完后处理
	}
	else {
		critical_value = true;
		if (polyLines.size() == 1) {
			return 0;
		}
		int NewIndex = getPosition(polyLines, slideLine); //新位置，并将slideLine设置为polyLines中对应线段的引用
		index = NewIndex;
		Point tempFrontVec, tempBackVec;		//向前向后到临界位置的方向向量
		double tempFrontDist, tempBackDist;		//向前向后到临界位置的偏移量
		Point tempCrossingPoint;				//相邻部分的交点
		if (index == 0 && backupLine.Pt1.locked == false) {							//推起始线且起始端点不固定
			Point slideVerticalVec = backupLine.Pt1 - slideLine.Pt1;
			Line backLine = polyLines[index + 1];
			Point backVec = backLine.getVector();
			//getValue
			tempCrossingPoint = getInsection(slideVerticalVec, backupLine.Pt1, backVec, backLine.Pt2);
			tempFrontDist = MIN_NUM;
			tempBackDist = sqrt(MIN_NUM * MIN_NUM * 2);
			tempFrontVec = backupLine.Pt1 - slideLine.Pt1;
			tempBackVec = backVec;
		}
		else if (index == polyLines.size() - 1 && backupLine.Pt2.locked == false) {  //推终止线且终止端点不固定
			Point slideVerticalVec = backupLine.Pt2 - slideLine.Pt2;
			Line frontLine = polyLines[index - 1];
			Point frontLineVec = frontLine.getVector();
			//getValue
			tempCrossingPoint = getInsection(slideVerticalVec, backupLine.Pt2, frontLineVec, frontLine.Pt1);
			tempFrontDist = sqrt(MIN_NUM * MIN_NUM * 2);
			tempBackDist = MIN_NUM;
			tempFrontVec = frontLineVec * (-1);
			tempBackVec = backupLine.Pt2 - slideLine.Pt2;
		}
		else {
			Line frontLine = polyLines[NewIndex - 1];
			Point frontLineVec = frontLine.getVector();
			Line backLine = polyLines[NewIndex + 1];
			Point backLineVec = backLine.getVector();
			//getValue
			tempCrossingPoint = getInsection(frontLineVec, frontLine.Pt1, backLineVec, backLine.Pt2);
			tempBackDist = tempFrontDist = sqrt(MIN_NUM * MIN_NUM / 2);
			tempFrontVec = frontLineVec * (-1);
			tempBackVec = backLineVec;
			index = NewIndex;  //位置发生变化
		}
		tempFrontVec = tempFrontVec / norm(tempFrontVec);
		tempBackVec = tempBackVec / norm(tempBackVec);
		Point frontStartPoint = tempCrossingPoint + tempFrontVec * tempFrontDist;
		Point backEndPoint = tempCrossingPoint + tempBackVec * tempBackDist;
		//give Value
		if (index == 0 && slideLine.Pt1.locked == false) {
			slideLine.Pt1 = polyLines[index].Pt1 = frontStartPoint;
			slideLine.Pt2 = polyLines[index].Pt2 = polyLines[index + 1].Pt1 = backEndPoint;
		}
		else if (index == polyLines.size() - 1 && slideLine.Pt2.locked == false) {
			slideLine.Pt1 = polyLines[index - 1].Pt2 = polyLines[index].Pt1 = frontStartPoint;
			slideLine.Pt2 = polyLines[index].Pt2 = backEndPoint;
		}
		else {
			slideLine.Pt1 = polyLines[index - 1].Pt2 = polyLines[index].Pt1 = frontStartPoint;
			slideLine.Pt2 = polyLines[index].Pt2 = polyLines[index + 1].Pt1 = backEndPoint;
		}
	}

	mergeLines(polyLines);
	//执行后处理
	if (postOn) slidePostProcessing(polyLines);

	if (m_inGreed) {		//取网格点
		for (auto& line : polyLines) {
			line.Pt1.x = round(line.Pt1.x), line.Pt1.y = round(line.Pt1.y);
			line.Pt2.x = round(line.Pt2.x), line.Pt2.y = round(line.Pt2.y);
		}
	}
	return 0;
}
// 确定推挤线和其他线的连接关系
void SlideLine::determineConnection(vector<Line>& lineVec, int index, Line& slideline) {
	int olddir, newdir; //参考点基于slideLine的方向
	bool signal = false;
	Point preCrossingPoint, backCrossingPoint;  //交点
	Point prePoint, backPoint; //靠前的点
	Point slideVec;  //slide线段的方向向量
	Point tempVec;  //和slide线段相交有交点的线段的方向向量
	Point offsetVec; //推挤方向向量

	Line tempLine;
	Line backUpSlideLine; //备份slideline
	Line newPINLine;  //推挤到端线位置，需要引出新的一条线
	Line preSlideLine = lineVec[index];  //推挤前推挤线段
	vector<Line> removeLineVec;  //需要移除的线段的集合
	vector<Line> backUpLineVec; //备份
	slideVec = slideline.Pt2 - slideline.Pt1;
	backUpLineVec = lineVec;
	backUpSlideLine = slideline;

	offsetVec = slideline.Pt2 - preSlideLine.Pt2;   // 线段的移动方向
	offsetVec = getSlideProjection(offsetVec, rotate(slideVec, 90));  // 真实推挤方向（法线方向的推挤方向

	if (index == (lineVec.size() - 1)) {  //终止线段
		backPoint = preSlideLine.Pt2;
		backCrossingPoint = (backPoint.locked == true) ? getPINCrossingPoint(backPoint, backUpSlideLine, false) : slideline.Pt2;
		slideline.Pt2 = lineVec[index].Pt2 = backCrossingPoint;
		if (backPoint.locked == true) {
			newPINLine.Pt1 = backCrossingPoint;
			newPINLine.Pt2 = backPoint;
			lineVec.emplace_back(newPINLine);
		}
	}
	if (index == 0) {   //起始线段
		prePoint = preSlideLine.Pt1;
		preCrossingPoint = (prePoint.locked == true) ? getPINCrossingPoint(prePoint, backUpSlideLine, true) : slideline.Pt1;
		slideline.Pt1 = lineVec[index].Pt1 = preCrossingPoint;
		if (prePoint.locked == true) {
			newPINLine.Pt1 = prePoint;
			newPINLine.Pt2 = lineVec[index].Pt1 = preCrossingPoint;  //赋值
			lineVec.insert(lineVec.begin(), newPINLine);
			signal = true;
		}
	}


	//往前SlideLine和前面线段的交点： 即SlideLine起点的确定
	for (int i = index - 1; i >= 0; --i) {
		tempLine = backUpLineVec[i];  //依次取出前面的每一条线段（包括推挤线段本身本身）
		tempVec = tempLine.Pt1 - tempLine.Pt2;
		prePoint = tempLine.Pt1;
		olddir = direction(preSlideLine, prePoint);
		newdir = direction(backUpSlideLine, prePoint);

		if (isParallel_lines(slideline, tempLine) && i != 0) {
			removeLineVec.emplace_back(tempLine);  // 没有遍历到起始线的平行线段都是要共线走的  --- 20240110 Update
			continue;
		}

		// 遇到垂直线提前判断  2024/03/26 GeUpdate
		if (CheckLinesPerpendicular(slideline, tempLine) && i != 0 && olddir != newdir) {
			removeLineVec.emplace_back(tempLine);
			continue;
		}

		if (olddir == newdir || !(inspectVectorsDirection(offsetVec, tempVec))) {   // 交点在这条线上
			preCrossingPoint = getInsection(slideVec, slideline.Pt2, tempVec, tempLine.Pt2);
			slideline.Pt1 = lineVec[i].Pt2 = lineVec[index].Pt1 = preCrossingPoint;
			break;
		}
		else if (olddir != newdir && i == 0) { //已经循环到起始线位置
			preCrossingPoint = getPINCrossingPoint(prePoint, backUpSlideLine, true);
			slideline.Pt1 = lineVec[i].Pt2 = lineVec[index].Pt1 = preCrossingPoint;
		}
		else {
			removeLineVec.emplace_back(tempLine);
		}
	}

	//往后SlideLine和后面线段的交点 ： 即SlideLine终点的确定
	for (int j = index + 1; j < backUpLineVec.size(); ++j) {
		tempLine = backUpLineVec[j];  //依次取出前面的每一条线段（包括推挤线段本身本身）
		tempVec = tempLine.Pt2 - tempLine.Pt1;
		backPoint = tempLine.Pt2;
		olddir = direction(preSlideLine, backPoint);
		newdir = direction(backUpSlideLine, backPoint);

		if (isParallel_lines(slideline, tempLine) && j != backUpLineVec.size() - 1) {
			removeLineVec.emplace_back(tempLine);  // 没有遍历到终止线的平行线段都是要共线走的  --- 20240110 Update
			continue;
		}

		if (olddir == newdir || !(inspectVectorsDirection(offsetVec, tempVec))) {   //交点在这条线上
			backCrossingPoint = getInsection(slideVec, slideline.Pt2, tempVec, tempLine.Pt2);
			(signal == true) ? lineVec[j + 1].Pt1 = lineVec[index + 1].Pt2 = slideline.Pt2 = backCrossingPoint
				: lineVec[j].Pt1 = lineVec[index].Pt2 = slideline.Pt2 = backCrossingPoint;
			break;
		}
		else if (olddir != newdir && j == backUpLineVec.size() - 1) { //已经循环到终止线位置
			backCrossingPoint = getPINCrossingPoint(backPoint, backUpSlideLine, false);
			(signal == true) ? lineVec[j + 1].Pt1 = lineVec[index + 1].Pt2 = slideline.Pt2 = backCrossingPoint
				: lineVec[j].Pt1 = lineVec[index].Pt2 = slideline.Pt2 = backCrossingPoint;
		}
		else {
			removeLineVec.emplace_back(tempLine);
		}
	}

	//删除推挤前后包含的线
	for (int k = 0; k < removeLineVec.size(); ++k) {
		removeLine(removeLineVec[k], lineVec);
	}
}
void SlideLine::inspectSingleLines(Line& slideLine, vector<Line>& lineVec) {
	int index;
	//int numSize;
	bool isParallel_Line;
	Line tempLine;
	vector<Line> reLineVec;  //备份

	//初始化
	isParallel_Line = false;
	//numSize = lineVec.size();
	reLineVec = lineVec;

	//删除长度为0的线段
	for (int i = 0; i < reLineVec.size(); ++i) {
		tempLine = reLineVec[i];
		if (tempLine.Pt1 == tempLine.Pt2) { //说明该线段起点和终点重合
			removeLine(tempLine, lineVec);
		}
	}

	if (lineVec.size() == 1) {
		return;
	}

	index = getPosition(lineVec, slideLine);  //index 只要不是 -1 一定是在中间，此时的slideLine是推挤完的
	//cout << "index:" << index << endl;
	if (index == -1) {
		cout << "Error! Not positioned to the pushed line!" << endl;
		return;   // 错误——定位失败
	}
	if (index == 0) {  //起始线
		isParallel_Line = isParallel_lines(slideLine, lineVec[index + 1]); //和后一条线是否平行
		if (isParallel_Line) {
			slideLine.setPt2(lineVec[index + 1].Pt2);
			lineVec[index] = slideLine;
			removeLine(lineVec[index + 1], lineVec);
			//index = index + 1; //slideLine 位置前移
			isParallel_Line = false;
		}
	}
	else if (index == lineVec.size() - 1) {
		isParallel_Line = isParallel_lines(slideLine, lineVec[index - 1]); //和前一条线是否平行
		if (isParallel_Line) {
			slideLine.setPt1(lineVec[index - 1].Pt1);
			lineVec[index] = slideLine;
			removeLine(lineVec[index - 1], lineVec);
			index = index - 1; //slideLine 位置前移
			isParallel_Line = false;
		}
	}
	else {
		isParallel_Line = isParallel_lines(slideLine, lineVec[index - 1]); //和前一条线是否平行
		if (isParallel_Line) {
			slideLine.setPt1(lineVec[index - 1].Pt1);
			lineVec[index] = slideLine;
			removeLine(lineVec[index - 1], lineVec);
			index = index - 1; //slideLine 位置前移
			isParallel_Line = false;
		}
		isParallel_Line = isParallel_lines(slideLine, lineVec[index + 1]); //和后一条线是否平行
		if (isParallel_Line) {
			slideLine.setPt2(lineVec[index + 1].Pt2);
			lineVec[index] = slideLine;
			removeLine(lineVec[index + 1], lineVec);
			index = index + 1; //slideLine 位置前移
			isParallel_Line = false;
		}
	}
}

void SlideLine::pushSingleSeg(Line& line, const Point& offset) {
	double angleNormal = atan2(line.Pt2.y - line.Pt1.y, line.Pt2.x - line.Pt1.x) + PI / 2;   // 线段的法线的角度
	Point vecNormal = Point(cos(angleNormal), sin(angleNormal));  //法线的单位向量
	double pushDistance = vecNormal * offset;   // 两向量点积：移动方向在法线方向的移动距离
	line.Pt1 = line.Pt1 + vecNormal * pushDistance;
	line.Pt2 = line.Pt2 + vecNormal * pushDistance;
}
//求解offset在baseVec方向上的投影方向
Point SlideLine::getSlideProjection(const Point& offsetVec, const Point& baseVec) {
	Point newBaseVec = baseVec;
	Point newOffsetVec = offsetVec;
	newBaseVec = newBaseVec / norm(newBaseVec);
	if (newOffsetVec != Point(0, 0)) {
		NormalizeVec(newOffsetVec);  // 单位化 -- 2024-01-11 Update
	}
	Point projectionVec;
	double isSameDir = newOffsetVec * newBaseVec;   // 判断两个向量方向是否相同（用单位向量）
	if (abs(isSameDir) < CountMinValue) {
		isSameDir = 0;
	}
	if (isSameDir >= 0) {    // Same
		projectionVec = newBaseVec * isSameDir;
	}
	else {
		newBaseVec = newBaseVec * (-1);
		double newDotValue = newOffsetVec * newBaseVec;
		projectionVec = newBaseVec * newDotValue;
	}

	return projectionVec;
}

//计算推挤线段和固定参考点的连线的新的交点  front用来判断往前算交点还是往后  front ==  true： 往前
Point SlideLine::getPINCrossingPoint(Point referencePoint, Line slideline, bool front) {
	int rPDir;
	double rotateAngle = 45;//默认逆时针45
	Point slideVec;
	Point crossingP;

	if (front == false) {  //终止线交换两点
		exchangePoints(slideline.Pt2, slideline.Pt1);
	}
	rPDir = direction(slideline, referencePoint);
	slideVec = slideline.Pt2 - slideline.Pt1;
	slideVec = slideVec / norm(slideVec);
	if (rPDir > 0) {
		rotateAngle = -rotateAngle;
	}

	crossingP = getInsection(slideVec, slideline.Pt2, rotate(slideVec, rotateAngle), referencePoint);

	return crossingP;
}
/*
* @brief 判断当前推挤线段是否到达临界值情况
* @line 存放推挤线
* @return true： can push  false：can't push
*/
bool SlideLine::judgement(Line preLine, const Line& line) const {
	double distance;

	Point vec_line = Point(line.Pt2) - line.Pt1;
	Point vecPreLine = Point(preLine.Pt2) - preLine.Pt1;
	double resultN;
	resultN = vec_line * vecPreLine;

	//cout << "vec_line：" << vec_line << endl;
	distance = sqrt(vec_line * vec_line);
	//cout << "distance：" << distance << endl;
	if (distance >= MIN_NUM && resultN > 0) {
		//cout << "mei you dadaolinjiezhi!" << endl;
		return true;
	}
	else
		return false;
}
//后处理
void SlideLine::slidePostProcessing(vector<Line>& polyLines) {
	if (polyLines.empty()) return;
	vector<Line> fixLines = { polyLines[0], polyLines.back() };
	vector<PPObs> nullObss;
	vector<double> spaces((int)polyLines.size(), 1);
	for (auto& line : polyLines) {
		line.width = 2;
	}
	//1.设置后处理对象基本参数
	post2.setWireSpacing(spaces);
	post2.setMiter(2);		//1.off,2.Minimal,3.Smooth,4Full
	//post2.setLockLines(lockLines_);
	//2.如果是差分线，设置差分线参数，如果不是，则不需要这一行
	//post2.setDiffInfo(DiffInfo(diffInfo_dirs, diffGaps_));
	//3.如果有需要，可修改后处理模式，1,2,3,4代表4种模式，会批量修改后处理的可选参数
	//4.如果有需要，调用不同接口可再次调整options，覆盖前面设置的参数（包括基本参数和可选参数）
	//post2.setAllowDRCs(true);
	//post2.setAllowEnlargeBoundary(true);
	//post2.setFixHalfObsLine(false);
	//post2.setFixBoundaryOnly(true);
	//post2.setFixCuteAngel(true);
	//post2.setRemainTimes(1.0);
	//5.调用后处理，算法正常结束返回0，异常结束返回负数，不同负数表示不同类型的异常
	int result = post2.HuglinesPostProcessing(polyLines, fixLines, nullObss);
	//6.调试，检查后处理是否正常返回
	if (result < 0) {
		std::cout << "后处理异常终止并返回，Error code= " << -result << endl;
	}
}



//2.推Pin
int SlideLine::pushOnePt(vector<Line>& polyLines, Point& pt, const Point offset) {
	bool isPt1 = false;
	bool moveNeighbor = false;
	int len = polyLines.size();
	int index = getPtLines(polyLines, pt, isPt1);

	Point& movePt = isPt1 ? polyLines[index].Pt1 : polyLines[index].Pt2;
	Point& movePtNeighbor = isPt1 ? polyLines[index - 1 < 0 ? len - 1 : index - 1].Pt2 : polyLines[index + 1 < len ? index + 1 : 0].Pt1;
	moveNeighbor = movePtNeighbor == movePt;
	movePt = movePt + offset;
	if (m_inGreed) {	//开启网格
		movePt.x = round(movePt.x), movePt.y = round(movePt.y);
	}
	if (!moveNeighbor) {	//不是首尾相连，说明退的是Pin点，推完需清空布线信息
		return 1;
	}
	movePtNeighbor = movePtNeighbor + offset;	//是首尾相连，则需要更新邻居点，并且更新布线信息
	if (m_inGreed) {	//开启网格
		movePtNeighbor.x = round(movePtNeighbor.x), movePtNeighbor.y = round(movePtNeighbor.y);
	}
	return 0;
}

int SlideLine::getPtLines(const std::vector<Line>& lines, const Point& pt, bool& isPt1) {
	//i为序号,isPt1标记是该序号线段的起点还是终点
	if (lines.empty()) return -1;
	for (int i = 0; i < lines.size(); ++i) {
		if (lines[i].Pt1 == pt) {
			isPt1 = true;
			return i;
		}
		else if (lines[i].Pt2 == pt) {
			isPt1 = false;
			return i;
		}
	}
	return -1;
}


//=======================================================================================================================

//=======================================================================================================================

//Hug模式
/*
* @避障主程序
* @ lineVec :推挤完的hugLine所在的整条线
* @hugLine : 经过障碍物的那条线【一般为推挤线段】
* @ preHugline: hugLine 推挤前的位置  -- 在对Polygon的hug中未调用，在对Line的hug中调用
* @obstacle: 障碍物的信息（障碍物的线）  在shovePreferred的调用中需要返回扩展后的障碍线：目前要求障碍物的类型一样
*/
void SlideLine::HugPreferred(vector<Line>& lineVec, Line hugLine, Line preHugline, vector<vector<Line> >& obstaclesVec) {

	vector<Point> hugPoints;  // 需要去hug 的所有点集
	vector<Line> tempSegs;  //一根线段hug完的新线段

	vector<Line> lineVec_backup = lineVec;	//2024.7.9,限制后处理范围

	//preProcessing:
	if (lineVec.empty() || obstaclesVec.empty()) {
		return;
	}

	// 20240228Update ： 根据线和障碍物的关系对线进行初始化
	//CheckPINPosition(lineVec, obstaclesVec);
	//logData(obstaclesVec, "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", true, true);
	//logData(lineVec, "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", false, false);
	vector<Line> ProcessingHugWire = lineVec;
	vector<Line> BackSegs = lineVec;
	int obsSize = obstaclesVec.size();
	for (int i = 0; i < obsSize; ++i) {

		// Step_1 : Get HugPoints
		CountProcessHugPoints(ProcessingHugWire, obstaclesVec[i], hugPoints);
		int startSegIndex = -1;
		int endSegIndex = -1;
		if (hugPoints.size() <= 1) {
			continue;       // Over Hug
		}

		//Step_2 : // Handling of HugPoints on Current obstacle
		//tempSegs = polyHugPointsHugLink(hugPoints, obstaclesVec[i], ProcessingHugWire, false);
		tempSegs = polyHugPointsHugLink(hugPoints, obstaclesVec[i], ProcessingHugWire, true);  // 01 - 03 Update
		// Step_3 : Handling and connecting both ends of obstacles
		startSegIndex = getPointPositionInLines(hugPoints[0], lineVec);                    // 11-22 Update : ProcessingHugWire -> lineVec
		endSegIndex = getPointPositionInLines(hugPoints[hugPoints.size() - 1], lineVec);   // 11-22 Update
		if (startSegIndex == -1 || endSegIndex == -1) {
			return;    // Get Wrong !!
		}

		Line tempSegmentLink_ = Line(lineVec[startSegIndex].Pt1, hugPoints[0]);      // 11-22 Update : ProcessingHugWire -> lineVec
		tempSegs.insert(tempSegs.begin(), tempSegmentLink_);
		CleanPointsNotOnObstacle(hugPoints, obstaclesVec[i]);   // Maybe is excessive !
		tempSegmentLink_ = Line(hugPoints[hugPoints.size() - 1], lineVec[endSegIndex].Pt2);   // 11-22 Update : ProcessingHugWire -> lineVec
		tempSegs.emplace_back(tempSegmentLink_);
		// Step_4 : Connection of the original line group
		vector<Line> Backup_LinesVec = lineVec;          // 11-22 Update 
		for (int j = 0; j < Backup_LinesVec.size(); ++j) {
			if (j >= startSegIndex && j <= endSegIndex) {
				removeLine(Backup_LinesVec[j], lineVec);
			}
		}

		for (auto& itemSegment : tempSegs) {
			lineVec.insert(lineVec.begin() + startSegIndex, itemSegment);
			startSegIndex++;
		}
		// Step_5 : Optimization of Last Wire
		//logData(obstaclesVec, "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", true, true);
		//logData(lineVec, "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", false, false);
		inspectSegmentsConnection(lineVec);
		//Step_6 : Loop && Update HugSegments
		ProcessingHugWire = lineVec;
	}

	//logData(obstaclesVec, "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", true, true);
	//logData(lineVec, "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", false, false);

	//2024.7.9,限制后处理范围===========================================
	//int start_index = 0,end_index = 0;	//从start_index（包含）到end_index（不包含）
	//for (size_t i = 0; i < lineVec_backup.size(); ++i) {
	//	if (lineVec_backup[i].Pt2 != lineVec[i].Pt2) {
	//		start_index = i;
	//		break;
	//	}
	//}
	//for (size_t i = lineVec_backup.size()-1,j = lineVec.size()-1; i >= 0 && j >= 0; --i,--j) {
	//	if (lineVec_backup[i].Pt1 != lineVec[j].Pt1) {
	//		end_index = i + 1;
	//		if (start_index < end_index)
	//			break;
	//		else
	//			cout<<"后处理的范围异常"<<endl;
	//	}
	//}

	HugPostProcessing(lineVec, obstaclesVec);  // 【后处理】
	//2024.7.9,限制后处理范围===========================================


	vector<Line> RealHugSegments;
	RetrunTrueHugSegments(BackSegs, lineVec, RealHugSegments);
	for (auto& item : RealHugSegments) {
		auto ptr = tmpHugSegs.insert(item);      // 初始化哈希表
	}
	//logData(obstaclesVec, "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", true, true);
	//logData(lineVec, "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", true, false);

	// Get SlideSeg 2024/3/27 GeUpdate
	vector<Line> MayUpdateSlideSegs;
	double ParallelDistance = LinesSpacing;
	MayUpdateSlideSegs = getMaySlideLines(lineVec, tempSlideHugSeg_, recordProHugLines, ParallelDistance);
	int SizeCountNum = MayUpdateSlideSegs.size();
	if (SizeCountNum == 0) {
		return;
	}

	if (SizeCountNum % 2 != 0) {
		SizeCountNum++;
	}
	SizeCountNum = (SizeCountNum / 2) - 1;  // 取中间的
	tempSlideHugSeg_ = MayUpdateSlideSegs[SizeCountNum];
	recordProHugLines = lineVec;

	return;
}
void SlideLine::HugPreferred(Wire& singleWire, const Line& HugSegment, const Line& preHugSegment, const vector<Polygon>& polyObstacles) {
	//preProcessing:
	if (singleWire.CentralSegments.empty() || polyObstacles.empty()) {
		return;
	}

	vector<Line> WiresLines = singleWire.CentralSegments;
	vector<vector<Line> > obstacles;

	for (auto& item : polyObstacles) {
		vector<Line> tempSegment = item.CentralSegments;
		obstacles.emplace_back(tempSegment);
	}
	HugPreferred(WiresLines, HugSegment, preHugSegment, obstacles);

	singleWire.SetCentralSegments(WiresLines);
}


// Bus 的新的 Hug
void SlideLine::BusHugPreferred
(
	vector<Wire>& BusHugWires,				//推挤影响的的折线组
	const vector<Line>& PreSlideSegments,	//推线的初始位置
	const vector<Line>& SlideSegments,		//鼠标选中的多根线段
	const vector<Polygon>& obstaclesP,		//多边形障碍物
	const bool& isHaveWireObs
) {
	if (obstaclesP.empty()) {
		return;
	}

	// polyWires Hug
	vector<vector<Line> > polyWiresVec;
	for (auto& itemWire_ : BusHugWires) {
		polyWiresVec.emplace_back(itemWire_.CentralSegments);
	}

	// poly Obstacles
	vector<vector<Line> > polyObstacles;
	for (auto& itemPolygon : obstaclesP) {
		polyObstacles.emplace_back(itemPolygon.CentralSegments);
	}

	polyLinesHug(polyWiresVec, PreSlideSegments, SlideSegments, polyObstacles, isHaveWireObs); // 这个里面的排序是只对索引做了排序操作，线的输入输出没变

	// afterHug
	for (int i = 0; i < BusHugWires.size(); ++i) {
		BusHugWires[i].SetCentralSegments(polyWiresVec[i]);
	}
}
void SlideLine::polyLinesHug(vector<vector<Line> >& vec_polyLines, vector<Line> prePushLines, vector<Line> hugLines, vector<vector<Line> > obstacle, const bool& haveWireObs) {
	if (obstacle.empty() || vec_polyLines.empty()) {
		return;
	}
	else {
		int SizeNumCount = obstacle.size();
		for (int i = 0; i < SizeNumCount; ++i) {  // 对是圆的障碍物优先处理
			vector<Line> itemLines = obstacle[i];
			if (itemLines[0].State == 2) {
				itemLines = generateOctagon(itemLines[0], prePushLines[0]);
				obstacle[i] = itemLines;   // May Get Bug.
			}
		}
	}

	//logData(obstacle, "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", true, true);
	//logData(vec_polyLines, "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", false, false);
	recordProHugLines.clear();

	// 外扩障碍物
	vector<vector<Line> > ExpandObstacles = obstacle;  // ExpandObstacles :未外扩的
	obstacle.clear();
	for (vector<Line> itemObs : ExpandObstacles) {
		itemObs = polygonExpand(itemObs, LinesSpacing, true);
		obstacle.emplace_back(itemObs);
	}

	obstacle = polygonUnion(obstacle);  // 重叠的障碍物合并

	// 整理障碍物
	for (int i = 0; i < obstacle.size(); ++i) {
		sortLines(obstacle[i]);
	}

	// 取一组障碍物的中心
	Point obsCenterPoint = getCenterOfObstacles(obstacle);

	vector<int> firstSideHugLinesID;    //Slide 后端Hug的线组
	vector<int> otherSideHugLinesID;    //Slide 前端Hug的线组

	//遍历所有hugLines: 分组Hug
	for (int i = 0; i < hugLines.size(); ++i) {
		if (!haveWireObs) {  // No Wire Obstacle
			Line tempHugSlideLine = prePushLines[i];
			Line tempHugLine = hugLines[i];
			int preHugDir = direction(tempHugSlideLine, obsCenterPoint);
			int nowHugDir = direction(tempHugLine, obsCenterPoint);
			if (preHugDir == nowHugDir) {
				firstSideHugLinesID.emplace_back(i);
			}
			else {
				otherSideHugLinesID.emplace_back(i);
			}
		}
		else {
			firstSideHugLinesID.emplace_back(i);
		}
	}

	//分组排序：靠近障碍物的中心的序号提前先Hug
	//processing firstsideHug
	int numSizeID = firstSideHugLinesID.size();
	Point SlideVecDir = getMidpoint(hugLines[0]) - getMidpoint(prePushLines[0]);
	SlideVecDir = getSlideProjection(SlideVecDir, rotate((prePushLines[0].Pt2 - prePushLines[0].Pt1), 90));
	if (numSizeID > 1) {
		for (int i = 0; i < numSizeID - 1; ++i) {
			for (int j = 0; j < numSizeID - i - 1; ++j) {
				int baseNum = firstSideHugLinesID[j];
				int nextNum = firstSideHugLinesID[j + 1];
				double tempBaseDistance = DoubleMaxNumValue;
				double tempNextDistance = DoubleMaxNumValue;
				if (!haveWireObs) {  //   use the Distance between CenterPoint To Segment check Dir
					tempBaseDistance = pointToLineDist(obsCenterPoint, prePushLines[baseNum]);  // hugLine -> prePushLines 2024/3/28 GeUpdate
					tempNextDistance = pointToLineDist(obsCenterPoint, prePushLines[nextNum]);  // hugLine -> prePushLines 2024/3/28 GeUpdate
					if (tempBaseDistance > tempNextDistance) {    //  front to back.
						exchangeTwoNum(firstSideHugLinesID[j], firstSideHugLinesID[j + 1]);
					}
				}
				else {    //   use Real SlideVec check Dir
					Line LineFront_ = prePushLines[baseNum];
					Line LineBack_ = prePushLines[nextNum];
					Point CrossPoint1_ = getInsection(SlideVecDir, LineFront_.Pt1, LineFront_.getVector(), LineFront_.Pt1);
					Point CrossPoint2_ = getInsection(SlideVecDir, LineFront_.Pt1, LineBack_.getVector(), LineBack_.Pt1);
					Point tempVecDir = CrossPoint1_ - CrossPoint2_; // ② ——> ①
					if (!inspectVectorsDirection(tempVecDir, SlideVecDir)) {
						exchangeTwoNum(firstSideHugLinesID[j], firstSideHugLinesID[j + 1]);    // Exchange Index.
					}
				}
			}
		}
	}

	//processing otherSideHug
	numSizeID = otherSideHugLinesID.size();
	if (numSizeID > 1) {
		for (int i = 0; i < numSizeID - 1; ++i) {
			for (int j = 0; j < numSizeID - i - 1; ++j) {
				int baseNum = otherSideHugLinesID[j];
				int nextNum = otherSideHugLinesID[j + 1];
				double tempBaseDistance = pointToLineDist(obsCenterPoint, prePushLines[baseNum]);  // hugLine -> prePushLines 2024/3/28 GeUpdate
				double tempNextDistance = pointToLineDist(obsCenterPoint, prePushLines[nextNum]);  // hugLine -> prePushLines 2024/3/28 GeUpdate

				if (tempBaseDistance < tempNextDistance) {   //  Remote processing first. back to front
					exchangeTwoNum(otherSideHugLinesID[j], otherSideHugLinesID[j + 1]);
				}
			}
		}
	}

	NormalHugDir = SlideVecDir * (-1);  // default: firstSideHugLinesID's Dir

	// 2024/3/21 GeUpdate Hug Wire : Attention to the position of obs_Wire
	if (haveWireObs) { // 根据障碍物位置和SlideDir确定Hug的顺序
		Line tempHugSeg = hugLines[firstSideHugLinesID[0]]; //Slide方向最靠前的hugSeg
		Line tempPreHugSeg = prePushLines[firstSideHugLinesID[0]];
		vector<Line> testTmpLines;
		testTmpLines.emplace_back(Line(tempPreHugSeg.Pt1, tempHugSeg.Pt1));
		testTmpLines.emplace_back(tempHugSeg);
		testTmpLines.emplace_back(Line(tempHugSeg.Pt2, tempPreHugSeg.Pt2));
		testTmpLines.emplace_back(tempPreHugSeg);
		vector<Point> tmpCrossPoints;
		for (auto& itemObs : obstacle) {
			tmpCrossPoints = getTwoLinesCrossingPoints(testTmpLines, itemObs, true);
			if (!tmpCrossPoints.empty()) {
				break;
			}
		}
		//  tmpCrossPoints is empty. obs is not in SlidePath
		if (tmpCrossPoints.empty()) {
			reverse(firstSideHugLinesID.begin(), firstSideHugLinesID.end());
			NormalHugDir = NormalHugDir * (-1);
		}
	}

	//Hug obstacles: firstSideHugLines
	/*logData(obstacle, "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", true, true);
	logData(prePushLines, "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", true, false);
	logData(hugLines, "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", true, false);
	logData(vec_polyLines, "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", false, false);*/
	//Initing
	vector<vector<Line> > BackWireLinesVec = vec_polyLines;
	vector<vector<Line> > BackOriginObs = obstacle;   // 外扩过的
	int processTime = 0;
	bool needHugOn_ = true;
	tempSlideHugSeg_ = prePushLines[0];

	//if (BusCheckAfterHug(vec_polyLines, BackOriginObs)) {  // Hug Check.
	//    needHugOn_ = false;
	//}

	while (needHugOn_) {
		processTime++;
		if (!tmpHugSegs.empty()) {
			tmpHugSegs.clear();
		}
		for (int i = 0; i < firstSideHugLinesID.size(); ++i) {
			if (i != 0) {
				Point OriginDir = getMidpoint(prePushLines[firstSideHugLinesID[i]]) - getMidpoint(prePushLines[firstSideHugLinesID[i - 1]]);
				NormalHugDir = getSlideProjection(OriginDir, rotate((prePushLines[0].Pt2 - prePushLines[0].Pt1), 90));
				//logData(vec_polyLines[firstSideHugLinesID[i - 1]], "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", false, false);
			}
			int tempLinesID = firstSideHugLinesID[i];
			/* First Step: HugObstacle */
			//logData(obstacle, "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", true, true);
			//logData(vec_polyLines[tempLinesID], "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", false, false);
			HugPreferred(vec_polyLines[tempLinesID], hugLines[tempLinesID], prePushLines[tempLinesID], obstacle);
			//logData(obstacle, "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", true, true);
			//logData(vec_polyLines[tempLinesID], "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", false, false);

			/* Second Step : linesExpand */
			//vector<Line> tempExpandLines = GroupLinesExpand(vec_polyLines[tempLinesID], LinesSpacing);
			vector<Line> tempExpandLines = polygonExpand(vec_polyLines[tempLinesID], LinesSpacing, false);
			//logData(tempExpandLines, "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", true, true);
			//logData(vec_polyLines[tempLinesID], "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", false, false);
			obstacle.emplace_back(tempExpandLines);
			clock_t ExpandEndTime = clock();
			/* Third Step: PolygonUnion */
			obstacle = polygonUnion(obstacle);
		}

		//Hug obstacles: otherSideHugLines 
		if (processTime == 1) {
			NormalHugDir = SlideVecDir;  // 标准方向的变换 2024/3/27 GeUpdate
		}
		for (int i = 0; i < otherSideHugLinesID.size(); ++i) {
			if (i != 0) {
				Point OriginDir = getMidpoint(prePushLines[otherSideHugLinesID[i]]) - getMidpoint(prePushLines[otherSideHugLinesID[i - 1]]);
				NormalHugDir = getSlideProjection(OriginDir, rotate((prePushLines[0].Pt2 - prePushLines[0].Pt1), 90));
				//logData(vec_polyLines[otherSideHugLinesID[i - 1]], "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", false, false);
			}
			int tempLinesID = otherSideHugLinesID[i];
			/* First Step: HugObstacle */
			//logData(obstacle, "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", true, true);
			//logData(vec_polyLines[tempLinesID], "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", false, false);
			HugPreferred(vec_polyLines[tempLinesID], hugLines[tempLinesID], prePushLines[tempLinesID], obstacle);
			//logData(obstacle, "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", true, true);
			//logData(vec_polyLines[tempLinesID], "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", false, false);

			if (i != otherSideHugLinesID.size() - 1) {
				/* Second Step : linesExpand */
				//vector<Line> tempExpandLines = GroupLinesExpand(vec_polyLines[tempLinesID], LinesSpacing);
				vector<Line> tempExpandLines = polygonExpand(vec_polyLines[tempLinesID], LinesSpacing, false);
				//logData(tempExpandLines, "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", true, true);
				//logData(vec_polyLines[tempLinesID], "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", false, false);
				obstacle.emplace_back(tempExpandLines);
				/* Third Step: PolygonUnion */
				obstacle = polygonUnion(obstacle);
			}
		}

		// 检查Hug的结果
		if (BusCheckAfterHug(vec_polyLines, ExpandObstacles)) {
			needHugOn_ = false;
			break;
		}

		if (processTime > 2) {  // Over Hug!
			break;
		}

		//logData(ExpandObstacles, "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", true, true);
		//logData(vec_polyLines, "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", false, false);

		// 有问题 --- 第一次算法纠正
		if (!firstSideHugLinesID.empty() && !otherSideHugLinesID.empty()) { // 两个线组都有线
			for (auto& itemNumId : otherSideHugLinesID) {
				firstSideHugLinesID.emplace_back(itemNumId);
			}
			//重新排序
			sortBusSlideDir(firstSideHugLinesID, prePushLines, SlideVecDir, true);
			// Re Initing
			NormalHugDir = SlideVecDir * (-1);
			otherSideHugLinesID.clear();
			obstacle.clear();
			vec_polyLines.clear();
			obstacle = BackOriginObs;
			vec_polyLines = BackWireLinesVec;
			continue;
		}
		// 已经在同一个线组了   --- 第2次算法纠正
		if (!firstSideHugLinesID.empty()) {
			reverse(firstSideHugLinesID.begin(), firstSideHugLinesID.end());
			NormalHugDir = NormalHugDir * (-1);
		}
		else {  // !otherSideHugLinesID.empty()
			reverse(otherSideHugLinesID.begin(), otherSideHugLinesID.end());
			NormalHugDir = NormalHugDir * (-1);
		}

		// Re Initing
		obstacle.clear();
		vec_polyLines.clear();
		obstacle = BackOriginObs;
		vec_polyLines = BackWireLinesVec;

	}

	// BusCheck Result  --- Slide Protect 2024/4/2
	//if (needHugOn_) {  // Error.
	//    vec_polyLines = BusHugPolyLinesRecord;
	//}
	//else {
	//    BusHugPolyLinesRecord = vec_polyLines;
	//}

}
// 求一个圆的外接正八边形
vector<Line> SlideLine::generateOctagon(const Line& BaseCircle, const Line& hugLine) {
	//Init 
	Point startPoint = hugLine.Pt1;
	Point endPoint = hugLine.Pt2;
	Point hugVec = endPoint - startPoint;
	Point circlecenterPoint = BaseCircle.circleCenter;
	double CircleRadius = BaseCircle.Radius;
	vector<Line> octagonLines;
	hugVec = hugVec / norm(hugVec);
	Point hugVertixL = getCircleVertix(hugVec, 112.5, circlecenterPoint, CircleRadius);
	Point hugVertixR = getCircleVertix(hugVec, 67.5, circlecenterPoint, CircleRadius);
	Line tempSegment = Line(hugVertixL, hugVertixR);
	double lengthR = norm(tempSegment);
	octagonLines.emplace_back(tempSegment);
	for (int i = 1; i < 7; ++i) {
		Point tempNewVec = rotate(hugVec, -45);
		Point newPointR = hugVertixR + tempNewVec * lengthR;
		tempSegment = Line(hugVertixR, newPointR);
		octagonLines.emplace_back(tempSegment);
		//Going on !
		hugVertixR = newPointR;
		hugVec = tempNewVec;
	}
	tempSegment = Line(hugVertixR, hugVertixL);
	octagonLines.emplace_back(tempSegment);

	return octagonLines;
}



vector<Line> SlideLine::polygonExpand(vector<Line> obstacle, double dist, bool close) {
	int PCI = 1;//扩大的倍数
	bool bFlag = isEncloseGraph(obstacle);
	//bool bFlag = close;

	vector<Point> obsPointVec = LinesToPoints(obstacle, bFlag);
	//vector<Point> obsPointVec = LinesToPoints(obstacle, close);
	vector<Line> expandLineVec = obstacle;
	
	return expandLineVec;
}
// 合并多边形
vector<vector<Line> > SlideLine::polygonUnion(vector<vector<Line>>obstacles) {
	
	//removeCollinerPoint(newobs);
	return obstacles;
}



/*
* @brief 得到圆的外切正八边形的两个顶点CD
* @vec 存放已知的方向向量
* @rotateAngle 若当前向量需要旋转则输入对应角度(默认顺时针)，反之input 0
* @circleP 圆的圆心坐标
* @radius 圆的半径
* @return : point
*/
Point SlideLine::getCircleVertix(Point vec, double rotateAngle, Point circleP, double radius) {
	Point newVec;
	Point outPoint;
	double length, veclength;
	Point unitVec;

	double rad = rotateAngle * PI / 180.0;
	newVec = rotate(vec, rotateAngle);
	veclength = norm(newVec);
	unitVec = newVec / veclength; //单位化
	length = abs(radius / sin(rad));

	outPoint = circleP + unitVec * length;

	//cout << "vecInit:" << vec << endl;
	//cout << "newVec:" << newVec << endl;
	//cout << "length:" << length << endl;
	//cout << "outPoint:" << outPoint << endl;

	return outPoint;
}
// 新的计算可能的Hug点—— 11.14
void SlideLine::CountProcessHugPoints(const vector<Line>& singleWires, const vector<Line>& ExpandedWires, vector<Point>& HugPoints) {
	//vector<vector<Line>> obss = { ExpandedWires };
	vector<Point> temp_Points;
	vector<Point> totalHugPoints_;
	HugPoints.clear();
	// 点是否在障碍物内部
	bool StartPointIn_ = false;
	bool EndingPointIn_ = false;
	bool needHugLines = false;
	totalHugPoints_.emplace_back(singleWires[0].Pt1);
	vector<Point> RealCrossingPoints;   //真实的交点
	for (auto& tempSegment : singleWires) {
		////// 先判断 线可有问题
		//needHugLines = isSegPolygonCross(tempSegment, ExpandedWires, false);
		//if (!needHugLines) {   // 没问题保存 Pt2 后退出
		//    totalHugPoints_.emplace_back(tempSegment.Pt2);
		//    StartPointIn_ = false;
		//    continue;
		//}

		EndingPointIn_ = pointInPolygon(tempSegment.Pt2, { ExpandedWires }, false);

		if (EndingPointIn_) {    // Pt2 In Polygon
			//bool CrossCheck = getSegAndPolyInsectionsBoost(tempSegment, ExpandedWires, temp_Points);
			temp_Points = insectionsOfLineToLines(tempSegment, ExpandedWires);
			if (!temp_Points.empty()) {
				pointsToNewVec(temp_Points, totalHugPoints_);
			}

			if (temp_Points.empty() && !StartPointIn_) {  // Pt1 Not && Pt2 In && No CrossingPoint : Wrong!
				int SideSegIndex = GetPointToSideMinDist(getMidpoint(tempSegment), ExpandedWires);
				if (SideSegIndex == -1) {  // 2024/3/21 GeUpdate
					continue;
				}
				Line NewTempLFirst = tempSegment;
				Line NewTempLSecond = ExpandedWires[SideSegIndex];
				Point CrosssingPoint = NewTempLFirst.getCrossingPoint(NewTempLSecond);
				temp_Points.emplace_back(CrosssingPoint);
				totalHugPoints_.emplace_back(CrosssingPoint);
			}
		}
		else {    // Pt2 Not In Polygon
			//bool CrossCheck = getSegAndPolyInsectionsBoost(tempSegment, ExpandedWires, temp_Points);
			temp_Points = insectionsOfLineToLines(tempSegment, ExpandedWires);
			if (!temp_Points.empty()) {
				pointsToNewVec(temp_Points, totalHugPoints_);
				totalHugPoints_.emplace_back(tempSegment.Pt2);
				//continue;
			}
			else {
				if (!StartPointIn_) {
					totalHugPoints_.emplace_back(tempSegment.Pt2);
				}
				else {  // Pt1 in && Pt2 Not In && No CrossP == Error
					int SideSegIndex = GetPointToSideMinDist(getMidpoint(tempSegment), ExpandedWires);
					if (SideSegIndex == -1) {  // 2024/3/21 GeUpdate
						continue;
					}
					Line NewTempLFirst = tempSegment;
					Line NewTempLSecond = ExpandedWires[SideSegIndex];
					Point CrosssingPoint = NewTempLFirst.getCrossingPoint(NewTempLSecond);
					temp_Points.emplace_back(CrosssingPoint);
					totalHugPoints_.emplace_back(CrosssingPoint);
					totalHugPoints_.emplace_back(tempSegment.Pt2);
				}
			}
		}

		///交点是真的Hug点
		if (!temp_Points.empty()) {
			// Check HugPoints是否在线段上
			for (auto& TempHugCrossPoint : temp_Points) {
				if (judgeCrossPoint(TempHugCrossPoint, tempSegment)) {
					RealCrossingPoints.emplace_back(TempHugCrossPoint);
				}

			}
			temp_Points.clear();   //迭代初始化
		}

		StartPointIn_ = EndingPointIn_;      // 迭代更新
	}

	// 线组需要处理
	int RealHugPointsSize = RealCrossingPoints.size();
	if (RealHugPointsSize > 1) {   // 小于 两个点不管他
		Point FirstHugPoint = RealCrossingPoints[0];
		Point LastHugPoint = RealCrossingPoints[RealHugPointsSize - 1];
		int FirstIndex = getPointPosition(totalHugPoints_, FirstHugPoint);
		int LastIndex = getPointPosition(totalHugPoints_, LastHugPoint);
		for (int i = 0; i < totalHugPoints_.size(); ++i) {
			if (FirstIndex <= i && i <= LastIndex) {
				HugPoints.emplace_back(totalHugPoints_[i]);
			}
		}

	}

}
/*
* @ updateTime : 2023/11/9
* @ Brief： // 单障碍物多Hug点求解最佳HugSegments
* @ hugPoints： 障碍物上的Hug点!!!注意是障碍物上面的
* @ singleObstacle：the obstacle that should Hug
* @ singleWireVec： hugPoints所在的整根线
* @ processMode: true -> Bus线处理中调用（需要考虑直接连接的线在同一条线段上否） false -> Hugprefered中调用：不考虑直接连接的Hug点是否在同一条线段上
*/
vector<Line> SlideLine::polyHugPointsHugLink(vector<Point>& hugPoints, const vector<Line>& singleObstacle, const vector<Line>& singleWireVec, const bool& processMode) {

	//Check HugPoints
	CheckHugPointsUniqueness(hugPoints);
	int NeedHugPointSize = hugPoints.size();

	//Init --- Bug Check
	vector<Line> BestHugSegments;
	if (NeedHugPointSize < 2 || singleObstacle.size() < 3) {
		return BestHugSegments;
	}

	vector<Point> NeedHugPoints = hugPoints;   // Back_up
	vector<Line> ExistedSegments;   //  The path that has already been Hug
	Line checkOnlyLinkSeg;
	bool GoingSearch = false;
	bool allowLink = true;  // 允许直连  // 11-13 修改

	// Hug routing from startPoint to endPoint
	CleanPointsNotOnObstacle(hugPoints, singleObstacle);

	bool StoEHugResWrong = false;  // Hug的结果检查判断 default : false == No Errors.
	if (hugPoints.size() > 1) {   // 11-17 update
		Point HugStartPoint = hugPoints[0];
		Point HugLastPoint = hugPoints[hugPoints.size() - 1];
		vector<Line> FirstHugOnlySegments;
		checkOnlyLinkSeg = Line(HugStartPoint, HugLastPoint);
		GoingSearch = isSegPolygonCross(checkOnlyLinkSeg, singleObstacle, false);
		if (processMode) {  // 需要考虑
			allowLink = TwoHugPointsOnSameSeg(HugStartPoint, HugLastPoint, singleWireVec);
		}

		if (!GoingSearch && allowLink) {
			FirstHugOnlySegments.emplace_back(checkOnlyLinkSeg);
		}
		else {
			FirstHugOnlySegments = TwoPointsGetHugSegments(HugStartPoint, HugLastPoint, singleObstacle, ExistedSegments);
			if (FirstHugOnlySegments.empty()) {  // avoid TwoPointsGetHugSegments Get Wrong.
				if (!LiveWireGetNewSegment(HugStartPoint, HugLastPoint, singleWireVec, FirstHugOnlySegments)) { // 2024/3/21 Ge Update
					FirstHugOnlySegments.emplace_back(checkOnlyLinkSeg);  // 建议不操作
					StoEHugResWrong = true;
				}
				else {
					bool CheckNewSegsRight = false;           // 默认需要更新
					for (auto& item : FirstHugOnlySegments) {   // 检查需要更换的线组
						CheckNewSegsRight = isSegPolygonCross(item, singleObstacle, false);
						if (CheckNewSegsRight) {
							break;
						}
					}

					if (CheckNewSegsRight) {
						StoEHugResWrong = true;
						FirstHugOnlySegments.clear();
						FirstHugOnlySegments.emplace_back(checkOnlyLinkSeg);  // 建议不操作 直接next
					}
				}
			}
		}

		BestHugSegments = FirstHugOnlySegments;
	}

	// Promise The Result is a Right Result.
	bool checkFirstPath = CheckTwoWiresCross(BestHugSegments, singleWireVec, false);    //2024-01-08 || Update
	if (checkFirstPath) {  // 出现和原线有交叉
		vector<Point> TotalNewCrossingPoints = getTwoLinesCrossingPoints(BestHugSegments, singleWireVec, true);
		// 这个就是新的Hug点对 singleWireVec 的 hug 点
		if (TotalNewCrossingPoints.size() > 1) {
			for (int i = 0; i < TotalNewCrossingPoints.size() - 1; ++i) {
				Point StartHugPoint = TotalNewCrossingPoints[i];
				Point EndHugPoint = TotalNewCrossingPoints[i + 1];
				vector<Line> TempHugLinesAdjust;  // 调整的线组
				if (LiveWireGetNewSegment(StartHugPoint, EndHugPoint, singleWireVec, TempHugLinesAdjust)) {
					bool CheckNewSegsRight = false;           // 默认需要更新
					for (auto& item : TempHugLinesAdjust) {   // 检查需要更换的线组
						CheckNewSegsRight = isSegPolygonCross(item, singleObstacle, false);
						if (CheckNewSegsRight) {
							/*StoEHugResWrong = true;*/
							break;
						}
					}

					if (!CheckNewSegsRight) { // 更换的线组没有问题的话就进行更新BestHugSegments
						int startSegIndex = -1;  // 原线的序列
						int endSegIndex = -1;
						startSegIndex = getPointPositionInLines(StartHugPoint, BestHugSegments);
						endSegIndex = getPointPositionInLines(EndHugPoint, BestHugSegments);
						if (startSegIndex == -1 || endSegIndex == -1) {
							break;  // Get Wrong Bug!
						}
						// HugSegments Link
						Line tempSegmentLink_ = Line(BestHugSegments[startSegIndex].Pt1, StartHugPoint);
						TempHugLinesAdjust.insert(TempHugLinesAdjust.begin(), tempSegmentLink_);
						tempSegmentLink_ = Line(EndHugPoint, BestHugSegments[endSegIndex].Pt2);
						TempHugLinesAdjust.emplace_back(tempSegmentLink_);

						// Step_4 : Connection of the original line group
						vector<Line> Backup_LinesVec = BestHugSegments;          // 11-22 Update 
						for (int j = 0; j < Backup_LinesVec.size(); ++j) {
							if (j >= startSegIndex && j <= endSegIndex) {
								removeLine(Backup_LinesVec[j], BestHugSegments);
							}
						}

						for (auto& itemSegment : TempHugLinesAdjust) {
							BestHugSegments.insert(BestHugSegments.begin() + startSegIndex, itemSegment);
							startSegIndex++;
						}

					}

				}

			}
		}
	}

	bool PairedHugResWrong = false;  // Hug的结果检查判断 default : false == No Errors.
	// Paired Hug routing in HugPoints
	if (NeedHugPointSize > 2) {
		hugPoints = NeedHugPoints;
		vector<Line> totalPairedHugSegments;
		vector<Line> tempBestHugLines;
		for (int i = 0; i < NeedHugPointSize - 1; ++i) {
			Point tempStartP_ = hugPoints[i];
			Point tempEndP_ = hugPoints[i + 1];
			checkOnlyLinkSeg = Line(tempStartP_, tempEndP_);
			GoingSearch = isSegPolygonCross(checkOnlyLinkSeg, singleObstacle, false);
			allowLink = true;  // 允许直连  // 11-13 修改
			if (processMode) {  // 需要考虑（处理Bus Wires）
				allowLink = TwoHugPointsOnSameSeg(tempStartP_, tempEndP_, singleWireVec);
			}
			if (!GoingSearch && allowLink) {
				tempBestHugLines.emplace_back(checkOnlyLinkSeg);
			}
			else {
				tempBestHugLines = TwoPointsGetHugSegments(tempStartP_, tempEndP_, singleObstacle, ExistedSegments);
			}

			// Iterative updates
			if (!tempBestHugLines.empty()) { // Remedial measures for misjudgment of isSegPolygonCross 24-1-11 update(Ensure that there is always a result for Hug between two HugPoints)
				for (auto& itemSeg : tempBestHugLines) {   // 两点之间去存储 HugSegment
					totalPairedHugSegments.emplace_back(itemSeg);
					if (GoingSearch) {
						ExistedSegments.emplace_back(itemSeg);
					}
				}
			}
			else {  // 说明TwoPointsGetHugSegments()返回的结果有问题 ： Wrong! Return Old WireSegs.
				if (!LiveWireGetNewSegment(tempStartP_, tempEndP_, singleWireVec, tempBestHugLines)) { // 2024/3/21 Ge Update
					totalPairedHugSegments.emplace_back(checkOnlyLinkSeg);
					PairedHugResWrong = true;
				}
				else {
					bool CheckNewSegsRight = false;         // 默认需要更新
					for (auto& item : tempBestHugLines) {   // 检查需要更换的线组
						CheckNewSegsRight = isSegPolygonCross(item, singleObstacle, false);
						if (CheckNewSegsRight) {
							break;
						}
					}

					if (!CheckNewSegsRight) {
						for (auto& itemSeg : tempBestHugLines) {   // 两点之间去存储 HugSegment
							totalPairedHugSegments.emplace_back(itemSeg);
						}
					}
					else {
						// Error : 有问题 ---- 不取两点的结果 
						PairedHugResWrong = true;
						totalPairedHugSegments.emplace_back(checkOnlyLinkSeg);
					}
				}
			}

			// 2024/5/16 Ge Update.
			if (i == 0 && CheckRoutePathSame(tempBestHugLines, BestHugSegments)) {
				return BestHugSegments;
			}

			tempBestHugLines.clear();
		}

		if (!PairedHugResWrong) {
			CheckHugSegmentsRight(totalPairedHugSegments);  // 检查两两HugPoint的走线结果
		}

		if (PairedHugResWrong && StoEHugResWrong) { // Error!
			BestHugSegments.clear();
			return BestHugSegments;
		}
		else if (!StoEHugResWrong && PairedHugResWrong) {
			return BestHugSegments;
		}
		else if (StoEHugResWrong && !PairedHugResWrong) {
			return totalPairedHugSegments;
		}
		else {
			// Comparison of the lengths of two Hug paths
			double FirstLength = DoubleMaxNumValue;  //11-16 update
			double SecondLength = DoubleMaxNumValue;
			FirstLength = countSegmentsLength(BestHugSegments);
			SecondLength = countSegmentsLength(totalPairedHugSegments);
			if (SecondLength < FirstLength) {   // Coefficient taken as 1
				BestHugSegments.clear();
				BestHugSegments = totalPairedHugSegments;
			}
		}
	}

	return BestHugSegments;
}
void SlideLine::HugPostProcessing(std::vector<Line>& hugSegments, const std::vector<std::vector<Line>>& existedObstacles) {

	if (hugSegments.empty()) {
		return;
	}
	/*
	//double CornerSegmentLength = (sqrt(2) - 1) * 2 * LinesSpacing;
	//HugPostObj.setMiter(MIN_NUM);
	post2.setLeastSegmentLength(MIN_NUM);

	post2.setWireSpacing(LinesSpacing);

	//std::vector<Line> fixLines;
	//std::vector<PPObs> obss;
	//for (auto polygon : existedObstacles) {
	//	obss.emplace_back(PPObs(polygon));
	//}
	//HugPostObj.HuglinesPostProcessing(hugSegments, fixLines, obss);
	post2.HuglinesPostProcessing(hugSegments, existedObstacles);
	*/


	//for (int i = 0; i < hugSegments.size(); ++i) {
	//	//输出log数据
	//	logData(hugSegments[i], "E:\\files\\02postProcess\\SlideTest02\\outPut\\LogData\\newlogdata10.txt", false, i == 0);
	//}

}
/*
* @ brief:// 从一根线中InputLines返回多根可能的SlideSegments
* @ InputLines : 输入的一组线中（需要在其中找到SlideSegment）
* @ BaseSegment： 前一条SlideSegment
* @ BaseWireSegs ： 前一条SlideSegment所在的整根线
* @ SlideSegsGap ： 两根线之间的间距（推挤不改变间距）
*/
vector<Line> SlideLine::getMaySlideLines(const vector<Line>& InputLines, const Line& BaseSegment, const vector<Line>& BaseWireSegs, const double& SlideSegsGap) {
	vector<Line> outPossibleLines;
	if (InputLines.empty()) {
		return outPossibleLines;
	}

	//logData(InputLines, "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", true, true);
	//logData(BaseWireSegs, "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", true, false);

	//Processing
	for (auto& itemSeg : InputLines) {
		bool CheckFirst = isParallel_lines(itemSeg, BaseSegment);
		if (CheckFirst) {
			bool inSlidePath = determineLineInSlidePath(itemSeg, BaseSegment);
			if (inSlidePath) {

				outPossibleLines.emplace_back(itemSeg);
			}
			else {
				// 是平行线对 BaseSegment 推挤相应距离判断 itemSeg 符合 SlideSegment 对齐规则
				//double ParallelDistance = getParallelLineDist(itemSeg, BaseSegment);
				double ParallelDistance = SlideSegsGap;  //不应该是最小线间距 || 应该是两根线本来的间距01 - 05 - Update

				Line SlideSegment = BaseSegment;
				vector<Line> SlideWireSegs = BaseWireSegs;
				int SlideIndex = getPosition(SlideWireSegs, SlideSegment);
				if (SlideIndex == -1) {  // 允许前面的线没处理好吗？
					break;
				}
				Point SlideVec = getMidpoint(itemSeg) - getMidpoint(SlideSegment);
				SlideVec = getSlideProjection(SlideVec, rotate((SlideSegment.Pt2 - SlideSegment.Pt1), 90));
				SlideVec = SlideVec / norm(SlideVec) * ParallelDistance;

				pushSingleSeg(SlideSegment, SlideVec);

				DetermineConnection(SlideWireSegs, SlideIndex, SlideSegment);
				//logData(SlideWireSegs, "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", false, false);

				inSlidePath = determineLineInSlidePath(itemSeg, SlideSegment);
				if (inSlidePath) {
					outPossibleLines.emplace_back(itemSeg);

				}
			}
		}
	}

	return outPossibleLines;
}
// 清除不在障碍物边上的点
void SlideLine::CleanPointsNotOnObstacle(vector<Point>& HugPoints, const vector<Line>& singleObstacle) {
	if (HugPoints.empty() || singleObstacle.size() < 3) {
		return;
	}

	// Init 
	int tempIndex = -1;
	//Loop check
	vector<Point> checkLoopPointsVec = HugPoints;
	for (Point& itemPoint_ : checkLoopPointsVec) {
		tempIndex = getPointPositionInLines(itemPoint_, singleObstacle);
		if (tempIndex == -1) {
			removePoint(itemPoint_, HugPoints);
		}

		tempIndex = -1;
	}
}
void SlideLine::DetermineConnection(vector<Line>& lineVec, int index, Line& slideline) {
	int olddir, newdir; //参考点基于slideLine的方向
	bool signal = false;
	Point preCrossingPoint, backCrossingPoint;  //交点
	Point prePoint, backPoint; //靠前的点
	Point slideVec;  //slide线段的方向向量
	Point tempVec;  //和slide线段相交有交点的线段的方向向量
	Point offsetVec; //推挤方向向量

	Line tempLine;
	Line backUpSlideLine; //备份slideline
	Line newPINLine;  //推挤到端线位置，需要引出新的一条线
	Line preSlideLine = lineVec[index];  //推挤前推挤线段
	vector<Line> removeLineVec;  //需要移除的线段的集合
	vector<Line> backUpLineVec; //备份
	slideVec = slideline.Pt2 - slideline.Pt1;
	backUpLineVec = lineVec;
	backUpSlideLine = slideline;

	offsetVec = slideline.Pt2 - preSlideLine.Pt2;   // 线段的移动方向
	offsetVec = getSlideProjection(offsetVec, rotate(slideVec, 90));  // 真实推挤方向（法线方向的推挤方向） --- 2024-01-10 Update
	//logData(lineVec, "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", true, true);
	vector<Line> testSlideLine;
	testSlideLine.emplace_back(slideline);
	//logData(testSlideLine, "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", false, false);

	if (index == (lineVec.size() - 1)) {  //终止线段
		backPoint = preSlideLine.Pt2;
		backCrossingPoint = (backPoint.locked == true) ? getPINCrossingPoint(backPoint, backUpSlideLine, false) : slideline.Pt2;
		slideline.Pt2 = lineVec[index].Pt2 = backCrossingPoint;
		if (backPoint.locked == true) {
			newPINLine.Pt1 = backCrossingPoint;
			newPINLine.Pt2 = backPoint;
			lineVec.emplace_back(newPINLine);
		}
	}

	if (index == 0) {   //起始线段
		prePoint = preSlideLine.Pt1;
		preCrossingPoint = (prePoint.locked == true) ? getPINCrossingPoint(prePoint, backUpSlideLine, true) : slideline.Pt1;
		slideline.Pt1 = lineVec[index].Pt1 = preCrossingPoint;
		if (prePoint.locked == true) {
			newPINLine.Pt1 = prePoint;
			newPINLine.Pt2 = lineVec[index].Pt1 = preCrossingPoint;  //赋值
			lineVec.insert(lineVec.begin(), newPINLine);
			signal = true;
		}
	}


	//往前SlideLine和前面线段的交点： 即SlideLine起点的确定
	for (int i = index - 1; i >= 0; --i) {
		tempLine = backUpLineVec[i];  //依次取出前面的每一条线段（包括推挤线段本身本身）
		tempVec = tempLine.Pt1 - tempLine.Pt2;
		prePoint = tempLine.Pt1;
		olddir = direction(preSlideLine, prePoint);
		newdir = direction(backUpSlideLine, prePoint);

		if (isParallel_lines(backUpSlideLine, tempLine) && i != 0) {
			removeLineVec.emplace_back(tempLine);  // 没有遍历到起始线的平行线段都是要共线走的  --- 20240110 Update
			continue;
		}

		// 遇到垂直线提前判断  2024/03/26 GeUpdate
		if (CheckLinesPerpendicular(slideline, tempLine) && i != 0 && olddir != newdir) {
			removeLineVec.emplace_back(tempLine);
			continue;
		}

		if (olddir == newdir || !(inspectVectorsDirection(offsetVec, tempVec))) {   // 交点在这条线上
			preCrossingPoint = getInsection(slideVec, slideline.Pt2, tempVec, tempLine.Pt2);
			slideline.Pt1 = lineVec[i].Pt2 = lineVec[index].Pt1 = preCrossingPoint;
			break;
		}
		else if (olddir != newdir && i == 0) { //已经循环到起始线位置
			preCrossingPoint = getPINCrossingPoint(prePoint, backUpSlideLine, true);
			slideline.Pt1 = lineVec[i].Pt2 = lineVec[index].Pt1 = preCrossingPoint;
		}
		else {
			removeLineVec.emplace_back(tempLine);
		}
	}
	//logData(lineVec, "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", false, false);

	//往后SlideLine和后面线段的交点 ： 即SlideLine终点的确定
	for (int j = index + 1; j < backUpLineVec.size(); ++j) {
		tempLine = backUpLineVec[j];  //依次取出前面的每一条线段（包括推挤线段本身本身）
		tempVec = tempLine.Pt2 - tempLine.Pt1;
		backPoint = tempLine.Pt2;
		olddir = direction(preSlideLine, backPoint);
		newdir = direction(backUpSlideLine, backPoint);

		if (isParallel_lines(backUpSlideLine, tempLine) && j != backUpLineVec.size() - 1) {
			removeLineVec.emplace_back(tempLine);  // 没有遍历到终止线的平行线段都是要共线走的  --- 20240110 Update
			continue;
		}

		if (olddir == newdir || !(inspectVectorsDirection(offsetVec, tempVec))) {   //交点在这条线上
			backCrossingPoint = getInsection(slideVec, slideline.Pt2, tempVec, tempLine.Pt2);
			(signal == true) ? lineVec[j + 1].Pt1 = lineVec[index + 1].Pt2 = slideline.Pt2 = backCrossingPoint
				: lineVec[j].Pt1 = lineVec[index].Pt2 = slideline.Pt2 = backCrossingPoint;
			break;
		}
		else if (olddir != newdir && j == backUpLineVec.size() - 1) { //已经循环到终止线位置
			backCrossingPoint = getPINCrossingPoint(backPoint, backUpSlideLine, false);
			(signal == true) ? lineVec[j + 1].Pt1 = lineVec[index + 1].Pt2 = slideline.Pt2 = backCrossingPoint
				: lineVec[j].Pt1 = lineVec[index].Pt2 = slideline.Pt2 = backCrossingPoint;
		}
		else {
			removeLineVec.emplace_back(tempLine);
		}
	}

	//删除推挤前后包含的线
	for (int k = 0; k < removeLineVec.size(); ++k) {
		removeLine(removeLineVec[k], lineVec);
	}
	//logData(lineVec, "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", true, true);
}
// Hug 后的 Bus 线检查  true : Pass ; false : No Pass   
bool SlideLine::BusCheckAfterHug(vector<vector<Line> >& InputBusWires, const vector<vector<Line> >& Onstacles) {
	if (InputBusWires.empty() || Onstacles.empty()) {
		return true;
	}
	vector<Line> CurrentCheckWire;
	vector<Point> MayCrossingPoints;
	// 检查线与线的关系有无交叉
	for (int i = 0; i < InputBusWires.size() - 1; ++i) {
		CurrentCheckWire = InputBusWires[i];
		for (int j = i + 1; j < InputBusWires.size(); ++j) {
			MayCrossingPoints = getTwoLinesCrossingPoints(CurrentCheckWire, InputBusWires[j], true);
			if (!MayCrossingPoints.empty()) {
				return false;
			}
		}
	}

	// 检查Bus和障碍物的关系
	for (int i = 0; i < InputBusWires.size(); ++i) {
		CurrentCheckWire = InputBusWires[i];
		for (int j = 0; j < Onstacles.size(); ++j) {
			//logData(CurrentCheckWire, "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", true, true);
			//logData(Onstacles[j], "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", false, false);
			if (CheckSingleWireObs(CurrentCheckWire, Onstacles[j])) {
				return false;  // Error.
			}

		}
	}

	return true;
}
// 检查单根线和障碍物的位置关系 return true: 交叉 + Error.
bool SlideLine::CheckSingleWireObs(const vector<Line>& inputLines, const vector<Line>& SingleObs) {
	if (inputLines.empty() || SingleObs.empty()) {
		return false;
	}
	bool CheckRes = false;
	for (auto& itemSeg : inputLines) {
		CheckRes = isSegPolygonCross(itemSeg, SingleObs, false);
		if (CheckRes) {
			return true;
		}
	}

	return false;
}
// 单根线的外扩（不同部分外扩不同的值）
vector<Line> SlideLine::GroupLinesExpand(const vector<Line>& inputGroupSegs, const double& StandardSpacing) {
	if (inputGroupSegs.empty() || StandardSpacing == 0) {
		return inputGroupSegs;
	}

	// 分组
	bool ChangeStatus = true;
	vector<Line> tmpSegs;
	vector<vector<Line> > standardGroup;  // 按照 StandardSpacing 外扩
	vector<vector<Line> > NotStandardGroup;  // 按照 StandardSpacing/2 外扩
	if (!tmpHugSegs.empty()) {
		for (auto& item : inputGroupSegs) {
			if (tmpHugSegs.count(item) > 0) {
				if (!ChangeStatus && !tmpSegs.empty()) { // 第一次切到这个状态
					NotStandardGroup.emplace_back(tmpSegs);
					tmpSegs.clear();
				}
				ChangeStatus = true;
			}
			else {
				if (ChangeStatus && !tmpSegs.empty()) {
					standardGroup.emplace_back(tmpSegs);
					tmpSegs.clear();
				}
				ChangeStatus = false;
			}
			tmpSegs.emplace_back(item);
		}
	}
	else {
		standardGroup.emplace_back(inputGroupSegs);
	}

	if (!tmpSegs.empty()) {
		if (ChangeStatus) {
			standardGroup.emplace_back(tmpSegs);
		}
		else {
			NotStandardGroup.emplace_back(tmpSegs);
		}

	}

	//Expand
	vector<Line> standardObs;
	vector<Line> NotStandardObs;
	vector<vector<Line> >outerObs;
	if (!standardGroup.empty()) {
		for (auto& itemSeg : standardGroup) {
			standardObs = polygonExpand(itemSeg, StandardSpacing, false);
			outerObs.emplace_back(standardObs);
		}
		//logData(outerObs, "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", true, true);
		//logData(standardGroup, "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", false, false);
	}

	if (!NotStandardGroup.empty()) {
		for (auto& itemSeg : NotStandardGroup) {
			NotStandardObs = polygonExpand(itemSeg, StandardSpacing / 2, false);
			outerObs.emplace_back(NotStandardObs);
		}
		//logData(outerObs, "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", true, true);
		//logData(NotStandardGroup, "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", false, false);
	}

	if (outerObs.size() > 1) {
		outerObs = polygonUnion(outerObs);
	}
	//logData(outerObs, "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", true, true);
	//logData(inputGroupSegs, "E:\\PostgraduateProgram\\VsProgram\\Slide\\SlideTest\\outPut\\LogData\\1226SlidePolyLines.txt", false, false);

	return outerObs.front();
}
//  // 检查Hug的结果线组有没有问题  -- 11-17 Update
void SlideLine::CheckHugSegmentsRight(vector<Line>& HugSegments) {
	int HugSegSize = 0;
	HugSegSize = HugSegments.size();
	if (HugSegSize < 2) {  // 2 Segments at least
		return;
	}

	Point targetPoint = HugSegments[HugSegSize - 1].Pt2;
	for (int i = 0; i < HugSegSize - 1; ++i) {
		Line tempSegment = HugSegments[i];
		bool TargetPointOn = judgeCrossPoint(targetPoint, tempSegment);
		if (TargetPointOn) {
			HugSegments[i].Pt2 = targetPoint;
			HugSegments.erase(HugSegments.begin() + i + 1, HugSegments.end());
			break;
		}
	}
}
// 判断两个线组是否含有交点 CheckEnding = true: 考虑端点（端点为交点判为相交）  --- 11-17 Update
bool SlideLine::CheckTwoWiresCross(const vector<Line>& WireOne, const vector<Line>& WireTwo, const bool& CheckEnding) {
	if (WireOne.empty() || WireTwo.empty()) {
		return false;
	}
	bool CrossResult = false;
	vector<Point> WireOnePointsVec = LinesToPoints(WireOne, false);
	vector<Point> WireTwoPointsVec = LinesToPoints(WireTwo, false);

	// Loop
	for (int i = 0; i < WireOne.size(); ++i) {
		Line tempTestSegment = WireOne[i];
		vector<Point> MayCrossingPoints = insectionsOfLineToLines(tempTestSegment, WireTwo);

		if (!MayCrossingPoints.empty()) {
			if (CheckEnding) {
				CrossResult = true;
				break;
			}
			else {
				vector<Point> BackPoints = MayCrossingPoints;
				for (auto& itemPoint : BackPoints) {
					if (!pointInPointsVec(itemPoint, WireOnePointsVec) && !pointInPointsVec(itemPoint, WireTwoPointsVec)) {
						//removePoint(itemPoint, MayCrossingPoints);
						CrossResult = true;
						break;
					}
				}
				//if (!MayCrossingPoints.empty()) {  //  maybe not need
				//    CrossResult = true;
				//    break;
				//}
			}
		}
	}

	return CrossResult;

}
//交换两个差分对  **********  11-19 Update
void SlideLine::exchangeTwoDPairsVec(PairWires& PairsLeft, PairWires& PairsRight) {
	PairWires transLinesVec;
	transLinesVec = PairsLeft;
	PairsLeft = PairsRight;
	PairsRight = transLinesVec;
}
// HugPoints唯一性检查
void SlideLine::CheckHugPointsUniqueness(vector<Point>& HugPoints) {
	if (HugPoints.empty()) {
		return;
	}

	vector<Point> basePointsVec = HugPoints;
	HugPoints.clear();

	for (Point& itemPoint : basePointsVec) {
		bool havePoint = pointInPointsVec(itemPoint, HugPoints);
		if (!havePoint) {
			HugPoints.emplace_back(itemPoint);
		}
	}
}
// 判断一根线的两点是否在同一根线上  11-13 更新  return true: On same Segment
bool SlideLine::TwoHugPointsOnSameSeg(const Point& FirstPoint, const Point& SecondPoint, const vector<Line>& singleWire) {
	if (singleWire.empty()) {
		return false;
	}
	//First Time
	int FirstIndex = getPointPositionInLines(FirstPoint, singleWire);
	int SecondIndex = getPointPositionInLines(SecondPoint, singleWire);
	if (FirstIndex == -1 || SecondIndex == -1) {  // Get Wrong.
		return false;
	}
	Line SameSegment = singleWire[FirstIndex];
	bool SecondPointOn = judgeCrossPoint(SecondPoint, SameSegment);

	//Second Time
	SameSegment = singleWire[SecondIndex];
	bool FirstPointOn = judgeCrossPoint(FirstPoint, SameSegment);

	if (SecondPointOn || FirstPointOn) {
		return true;
	}
	else {
		return false;
	}
}
/*
* @ updateTime : 2023/11/9
* @ Brief： //新的两点之间直接取Hug线段的方案
* @ StartPoint & EndingPoint： Input Two Points
* @ avoidObstacle：the obstacle that StartPoint & EndingPoint should Hug
* @ ExistedSegments: The line segment that has already been traversed in the avoidObstacle
*/
vector<Line> SlideLine::TwoPointsGetHugSegments(const Point& StartPoint, const Point& EndingPoint, const vector<Line>& avoidObstacle, const vector<Line>& ExistedSegments) {
	//Bug ----> Exit
	vector<Line> outputSegments;  // print huglines
	if (avoidObstacle.size() < 3) {
		return outputSegments;
	}

	//Init Data
	vector<Point> AllHugOnlyPointsVec = LinesToPoints(avoidObstacle, true);           // Enclose
	vector<Point> AlreadyTraversedPointsVec = LinesToPoints(ExistedSegments, false);  // unEnclosed

	// Traverse the point set AllHugOnlyPointsVec, adding the starting and ending points
	int traverseMaxCount = AllHugOnlyPointsVec.size();
	int StartPointPositionIndex, EndPointPositionIndex;
	StartPointPositionIndex = EndPointPositionIndex = -1;
	Point StartSidePoint, EndSidePoint;
	bool inStartP_Segment = false;
	bool inEndP_Segment = false;

	for (int i = 0; i < traverseMaxCount; ++i) {
		Point BaseLeftPoint_ = AllHugOnlyPointsVec[i];
		Point BaseRightPoint_;
		if (i != traverseMaxCount - 1) {  // Not last Point
			BaseRightPoint_ = AllHugOnlyPointsVec[i + 1];
		}
		else {
			BaseRightPoint_ = AllHugOnlyPointsVec[0];
		}
		Line CheckSegment = Line(BaseLeftPoint_, BaseRightPoint_);
		//if (StartPointPositionIndex == -1) {
		//    inStartP_Segment = judgeCrossPoint(StartPoint, CheckSegment);
		//}
		inStartP_Segment = judgeCrossPoint(StartPoint, CheckSegment);
		if (inStartP_Segment) {
			StartPointPositionIndex = i + 1;
			StartSidePoint = AllHugOnlyPointsVec[i];
			//inStartP_Segment = false;
			//AllHugOnlyPointsVec.insert(AllHugOnlyPointsVec.begin() + i + 1, StartPoint);
		}

		inEndP_Segment = judgeCrossPoint(EndingPoint, CheckSegment);
		if (inEndP_Segment) {
			EndPointPositionIndex = i + 1;
			EndSidePoint = AllHugOnlyPointsVec[i];
			//AllHugOnlyPointsVec.insert(AllHugOnlyPointsVec.begin() + i + 1, EndingPoint);
		}
	}

	//Bug ----> Exit
	if (StartPointPositionIndex == -1 || EndPointPositionIndex == -1) {
		return outputSegments;
	}

	//Insert points
	StartPointPositionIndex = getPointPosition(AllHugOnlyPointsVec, StartSidePoint) + 1;
	AllHugOnlyPointsVec.insert(AllHugOnlyPointsVec.begin() + StartPointPositionIndex, StartPoint);
	EndPointPositionIndex = getPointPosition(AllHugOnlyPointsVec, EndSidePoint) + 1;
	AllHugOnlyPointsVec.insert(AllHugOnlyPointsVec.begin() + EndPointPositionIndex, EndingPoint);

	//Reassign
	StartPointPositionIndex = getPointPosition(AllHugOnlyPointsVec, StartPoint);
	EndPointPositionIndex = getPointPosition(AllHugOnlyPointsVec, EndingPoint);

	int backStartIndex_ = StartPointPositionIndex;  // back_up
	int backEndIndex_ = EndPointPositionIndex;

	// Points grouping
	vector<Point> Group_One;
	vector<Point> Group_Second;
	traverseMaxCount = AllHugOnlyPointsVec.size();  //resetting
	Group_One.emplace_back(StartPoint);  // Starting from the starting point
	Group_Second.emplace_back(StartPoint);
	// Search for Endpoint from StartPoint autoincrement
	while (StartPointPositionIndex != EndPointPositionIndex) {
		if (StartPointPositionIndex == traverseMaxCount - 1) {
			StartPointPositionIndex = 0;  // Loop to start position
		}
		else {
			StartPointPositionIndex++;   // Not the last element self adding
		}
		Group_One.emplace_back(AllHugOnlyPointsVec[StartPointPositionIndex]);

	}

	// Finding Endpoints from StartPoint Subtraction
	StartPointPositionIndex = backStartIndex_;
	EndPointPositionIndex = backEndIndex_;
	while (StartPointPositionIndex != EndPointPositionIndex) {
		if (StartPointPositionIndex == 0) {
			StartPointPositionIndex = traverseMaxCount - 1;  // Loop to start position
		}
		else {
			StartPointPositionIndex--;   // Not the last element self adding
		}
		Group_Second.emplace_back(AllHugOnlyPointsVec[StartPointPositionIndex]);
	}

	// Compare wiring groups
	vector<Line> Group_OneSegments;
	vector<Line> Group_SecondSegments;

	if (AlreadyTraversedPointsVec.empty()) {
		Group_OneSegments = PointsToLines(Group_One, false);
		Group_SecondSegments = PointsToLines(Group_Second, false);

		double GroupOneDist = countSegmentsLength(Group_OneSegments);
		double GroupSecondDist = countSegmentsLength(Group_SecondSegments);

		outputSegments = GroupOneDist > GroupSecondDist ? Group_SecondSegments : Group_OneSegments;
		//return outputSegments;
		// 所选线组要在前一条的指定方向上 --- ！不能绕线 2024/3/27 GeUpdate
		if (!recordProHugLines.empty()) { // 非第一条线
			// Step_1 : get Possble SlideSeg
			vector<Line> MayUpdateSlideSegs;
			double ParallelDistance = LinesSpacing;
			MayUpdateSlideSegs = getMaySlideLines(outputSegments, tempSlideHugSeg_, recordProHugLines, ParallelDistance);
			int SizeCountNum = MayUpdateSlideSegs.size();
			if (SizeCountNum != 0) {
				if (SizeCountNum % 2 != 0) {
					SizeCountNum++;
				}
				SizeCountNum = (SizeCountNum / 2) - 1;  // 取中间的
				Line SlideHugSeg = MayUpdateSlideSegs[SizeCountNum];
				// Step_2 : Check dir
				Point TmpSlideVecDir = getMidpoint(SlideHugSeg) - getMidpoint(tempSlideHugSeg_);
				TmpSlideVecDir = getSlideProjection(TmpSlideVecDir, rotate((SlideHugSeg.Pt2 - SlideHugSeg.Pt1), 90));
				if (inspectVectorsDirection(TmpSlideVecDir, NormalHugDir)) {
					return outputSegments;
				}
				else {
					return (GroupOneDist < GroupSecondDist ? Group_SecondSegments : Group_OneSegments);
				}
			}
		}
	}
	else {

		CheckHugPointsUniqueness(Group_One);  // 12-29 Update
		removePoint(StartPoint, AlreadyTraversedPointsVec);

		if (IntersectionPointsVec(AlreadyTraversedPointsVec, Group_One)) {
			Group_SecondSegments = PointsToLines(Group_Second, false);
			outputSegments = Group_SecondSegments;
		}
		else {
			Group_OneSegments = PointsToLines(Group_One, false);
			outputSegments = Group_OneSegments;
		}
	}

	return outputSegments;
}
//判断点集pointsVec2中含有pointsVec1中的点否 // 2023/11/9 update
bool SlideLine::IntersectionPointsVec(const vector<Point>& pointsVec1, const vector<Point>& pointsVec2) {
	if (pointsVec1.empty() || pointsVec2.empty()) {
		return false;
	}

	bool isHavePoint = false;
	for (auto& itemPoint : pointsVec1) {
		bool havePoint = pointInPointsVec(itemPoint, pointsVec2);
		if (havePoint) {
			isHavePoint = true;
			break;
		}
	}

	return isHavePoint;
}








